package cn.newtouch.basic.service.impl;

import cn.newtouch.basic.constant.RegisterConstant;
import cn.newtouch.basic.exception.BusinessException;
import cn.newtouch.basic.service.IVerifyCodeService;
import cn.newtouch.basic.util.SmsSendUtil;
import cn.newtouch.basic.util.StrUtils;
import cn.newtouch.basic.util.VerifyCodeUtils;
import cn.newtouch.user.domain.User;
import cn.newtouch.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.Map;
import java.util.concurrent.TimeUnit;


@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    /**
     * 图形验证码实现类
     */
    @Override
    public String getVerifyCode(String key) {
        // 1. 判断key是否为空 工具类为org.springframework.util提供的
        if(StringUtils.isEmpty(key)){
           throw new BusinessException("key不能为空！");
        }

        // 2. 生成随机验证码
        String code = StrUtils.getComplexRandomString(4);

        // 3. 把验证码的值存储到Redis,     key 验证码  多长时间    时间单位：分
        redisTemplate.opsForValue().set(key,code,3, TimeUnit.MINUTES);

        // 4. 把验证码的值合并到图片,把图片使用Base64编码, 并且返回base64编码的字符串
        return  VerifyCodeUtils.verifyCode(100,40,code);

    }


    /**
     * 短信验证码实现类
     */
    @Override
    public void smsCode(Map<String, String> map) {
        //map传参 里面包含前端传来的参数
        String phone = map.get("phone");  // 手机号
        String imageCode = map.get("imageCode");  // 图形验证码
        String imageCodeKey = map.get("imageCodeKey"); // 图形验证码对应的key值
        //1.校验是否为空 工具类为org.springframework.util提供的
        if(StringUtils.isEmpty(phone)
                        || StringUtils.isEmpty(imageCode)
                        ||StringUtils.isEmpty(imageCodeKey)
        ){
           throw new BusinessException("参数不能为空！！");
        }
        //2.图形验证码校验  存在redis里面的 通过key获取value（图像验证码）
        Object obj = redisTemplate.opsForValue().get(imageCodeKey);
        //如果图像验证码为空
        if(obj==null){
            throw new BusinessException("图像验证码已经过期，请重新刷新点击获取！！");
        }
        //如果图像验证码不为空 判断用户输入的是否和验证图片上的一致
        if(!obj.toString().equalsIgnoreCase(imageCode)){
            //如果不一致 提示用户
            throw new BusinessException("图像验证码输入错误，请重新输入！！");
        }
        //3.校验手机号是否被注册
        //通过电话号码查是否有人注册过
        User user=userMapper.findByPhone(phone);
        //如果user不为空
        if(user!=null){
            //提示用户
            throw new BusinessException("手机号已经被注册，请直接登录！！");
        }

        //4.判断是否是第一次发送请求，或者是验证码过期  从redis中获取  手机号+业务键
        Object value = redisTemplate.opsForValue().get(phone + RegisterConstant.PHONEREGISTER);

        //code存验证码的
        String code=null;

        //如果没取到
        if(value==null){
            //是第一次发送请求，重新生成验证码（工具类生成）
            code=StrUtils.getComplexRandomString(6);
        }else{
            //如果取到了 判断是否超过了一分钟
            String redisTime = value.toString().split(":")[1];
            //把时间戳转成Long 类型的
            Long ltime=Long.valueOf(redisTime);
            //如果不是第一次 并且时间在一分钟以内
            if(System.currentTimeMillis()-ltime<1*60*1000){
                throw new BusinessException("一分钟只能发送一次，请稍后重试！！");
            }else{
                //如果不是第一次 并且时间在1-3分钟 刷新过期时间
                code=value.toString().split(":")[0];
            }
        }
        //5.把code存入redis中       K：手机号+业务键  V：验证码：时间戳   多长：3  时间单位：分钟
        redisTemplate.opsForValue().set(phone + RegisterConstant.PHONEREGISTER,code+":"+System.currentTimeMillis(),3,TimeUnit.MINUTES);

        //6.发送短信给用户(工具类发送)
        SmsSendUtil.smsSend(phone,"您的验证码为："+code+",请在三分钟之内验证！！");

        System.out.println("您的验证码为："+code+",请在三分钟之内验证！！");
    }


    /**
     * 微信绑定的验证码
     * @param map
     */
    @Override
    public void binderSmsCode(Map<String, String> map) {
        //map传参 里面包含前端传来的参数
        String phone = map.get("phone");  // 手机号

        if(StringUtils.isEmpty(phone)){
            throw new BusinessException("手机号不能为空！！");
        }

        //2.判断是否是第一次发送请求，或者是验证码过期  从redis中获取  手机号+业务键
        Object value = redisTemplate.opsForValue().get(phone + RegisterConstant.WXBINDER);

        //code存验证码的
        String code=null;

        //如果没取到
        if(value==null){
            //是第一次发送请求，重新生成验证码（工具类生成）
            code=StrUtils.getComplexRandomString(6);
        }else{
            //如果取到了 判断是否超过了一分钟
            String redisTime = value.toString().split(":")[1];
            //把时间戳转成Long 类型的
            Long ltime=Long.valueOf(redisTime);
            //如果不是第一次 并且时间在一分钟以内
            if(System.currentTimeMillis()-ltime<1*60*1000){
                throw new BusinessException("一分钟只能发送一次，请稍后重试！！");
            }else{
                //如果不是第一次 并且时间在1-3分钟 刷新过期时间
                code=value.toString().split(":")[0];
            }
        }
        //3.把code存入redis中       K：手机号+业务键  V：验证码：时间戳   多长：3  时间单位：分钟
        redisTemplate.opsForValue().set(phone + RegisterConstant.WXBINDER,code+":"+System.currentTimeMillis(),3,TimeUnit.MINUTES);

        //4.发送短信给用户(工具类发送)
        //SmsSendUtil.smsSend(phone,"您的验证码为："+code+",请在三分钟之内验证！！");

        System.out.println("您的验证码为："+code+",请在三分钟之内验证！！");

    }




}
